class Dialog {
  constructor(component, props, events, meta) {
    this.key = `key_${(new Date()).getTime()}_${parseInt(Math.random() * Math.random() * 1000000)}`
    this.component = component
    this.props = props
    this.events = events
    this.meta = meta
    this.show = false
    this.render = true
    this.confirmBtnLoading = false
    this.cancelBtnLoading = false
  }
}
// 滚动加载类
class ScrollModel {
  /**
   *
   * @param {Object} container 容器Dom
   * @param {Array} dataSource 数据源
   * @param {Number} showLimit 显示数量限制，默认为10
   * @param {Object} extras 扩展参数
   * @param {Object} extras.pullUpLoad 上拉配置项，属性：threshold（Number）阈值，距离边缘为多少时触发事件，默认为10
   * @param {Object} extras.pullDownLoad 下拉配置项，属性：threshold（Number）阈值，距离边缘为多少时触发事件，默认为10
   * @param {Number} extras.rowHeightEstimation 预设的每条数据行高，默认值为48(px)
   */
  constructor(container, dataSource, showLimit = 10, extras) {
    // 容器Dom
    this.container = container
    // 数据源
    this.dataSource = dataSource
    // 显示数量限制
    this.showLimit = showLimit
    // 真实展示数据
    this.showData = []

    // 数据头指针，记录当前展示的数据首所在的索引位置
    this.headIndex = 0
    // 数据尾指针，记录当前展示的数据尾所在的索引位置
    this.tailIndex = this.showLimit
    // 上拉加载的开关，强制要用户离开阈值区再进入才能再次触发上拉加载
    this.isPullUpSwitch = true
    // 用于做300ms的节流
    this.pullUpLoading = false
    // 用于做300ms的节流
    this.pullDownLoading = false
    // 缓存数据组数，常量，可调整，默认2组
    this.CACHE_DEFAULT = 2
    // 缓存上一次的scrollTop值，用于判断用户是上拉还是下拉
    this.scrollTopCache = 0
    // 做初始化处理，根据展示数据条数设置数组
    // 补充，初始化数量少于limit数量时，仅获取实际数量
    if (dataSource && Array.isArray(dataSource)) {
      const limit = dataSource.length > showLimit ? showLimit : dataSource.length
      for (let i = 0; i < limit; i++) {
        this.showData.push(dataSource[i])
      }
    }
  }

  // 判断设备是否ios
  isIOS() {
    return /iPhone|iPad/i.test(navigator.userAgent)
  }

  // 获取展示数据数组
  getShowData() {
    return this.showData
  }

  // 初始化绑定滚动事件
  initEvent() {
    if (this.container) {
      this.container.onscroll = event => {
        console.log(event.target.scrollTop, this.scrollTopCache)
        if (event.target.scrollTop - this.scrollTopCache <= 0) {
          // 往下拖
          this.handlePullDownLoadEvent(event)
        } else {
          // 往上拖
          this.handlePullUpLoadEvent(event)
        }
        this.scrollTopCache = event.target.scrollTop
      }
    }
  }

  // 解除事件绑定
  unbindEvent() {
    if (this.container) {
      this.container.onscroll = null
    }
  }

  // 处理上拉
  handlePullUpLoadEvent(event) {
    const threshold =
      this.extras &&
        this.extras.pullUpLoad &&
        this.extras.pullUpLoad.threshold !== undefined &&
        this.extras.pullUpLoad.threshold > 10
        ? this.extras.pullUpLoad.threshold
        : 10
    if (
      event.target.scrollTop + event.target.offsetHeight >=
      event.target.scrollHeight - threshold &&
      this.isPullUpSwitch
    ) {
      if (!this.pullUpLoading) {
        this.pullUpLoading = true
        const spliceCount = this.handlePullUpUpdate()
        if (spliceCount) {
          // 超过缓存2组后，会删减数据，所以需要重新调整一下scrollTop的位置
          const rowHeightEstimation =
            this.extras && this.extras.rowHeightEstimation
              ? this.extras.rowHeightEstimation
              : 48
          this.container.scrollTop -= rowHeightEstimation * spliceCount
        }

        if (this.pullUpLoadingTimeout) {
          clearTimeout(this.pullUpLoadingTimeout)
        }
        this.pullUpLoadingTimeout = setTimeout(() => {
          this.pullUpLoading = false
        }, 300)
      }
    }
    this.isPullUpSwitch =
      event.target.scrollTop + event.target.offsetHeight <
      event.target.scrollHeight - threshold
  }

  // 处理下拉
  handlePullDownLoadEvent(event) {
    const threshold =
      this.extras &&
        this.extras.pullDownLoad &&
        this.extras.pullDownLoad.threshold !== undefined &&
        this.extras.pullDownLoad.threshold > 10
        ? this.extras.pullDownLoad.threshold
        : 10
    if (event.target.scrollTop <= threshold) {
      // 判断达到阈值，执行更新事件
      if (!this.pullDownLoading) {
        this.pullDownLoading = true
        const spliceCount = this.handlePullDownUpdate()
        if (spliceCount) {
          // 超过缓存2组后，会删减数据，所以需要重新调整一下scrollTop的位置
          const rowHeightEstimation =
            this.extras && this.extras.rowHeightEstimation
              ? this.extras.rowHeightEstimation
              : 48
          this.container.scrollTop += rowHeightEstimation * spliceCount
        }
        if (this.pullDownLoadingTimeout) {
          clearTimeout(this.pullDownLoadingTimeout)
        }
        // 做300ms节流
        this.pullDownLoadingTimeout = setTimeout(() => {
          this.pullDownLoading = false
        }, 300)
      }
    }
  }

  // 处理上拉数据更新
  handlePullUpUpdate() {
    const arr = []
    if (this.tailIndex < this.dataSource.length) {
      const newTailIndex = Math.min(
        this.tailIndex + this.showLimit,
        this.dataSource.length
      )
      // 上拉
      for (let i = this.tailIndex; i < newTailIndex; i++) {
        arr.push(this.dataSource[i])
      }
      this.showData.splice(this.showData.length, 0, ...arr)
      this.tailIndex = newTailIndex
      if (
        this.showData.length > this.showLimit * (this.CACHE_DEFAULT + 1) &&
        !this.isIOS()
      ) {
        // 数据超过预设展示条数，做删减（仅在非IOS端，IOS端存在阻尼回弹，体验不佳，不做删减）
        const distance =
          this.showData.length - this.showLimit * (this.CACHE_DEFAULT + 1)
        this.showData.splice(0, distance)
        this.headIndex += distance
        return distance
      }
    }

    return false
  }

  // 处理下拉数据更新
  handlePullDownUpdate() {
    const arr = []
    if (this.headIndex >= 0) {
      const newHeadIndex = Math.max(this.headIndex - this.showLimit, 0)
      // 下拉
      for (let i = newHeadIndex; i < this.headIndex; i++) {
        arr.push(this.dataSource[i])
      }
      this.showData.splice(0, 0, ...arr)
      this.headIndex = newHeadIndex
      if (
        this.showData.length > this.showLimit * (this.CACHE_DEFAULT + 1) &&
        !this.isIOS()
      ) {
        // 数据超过预设展示条数，做删减（仅在非IOS端，IOS端存在阻尼回弹，体验不佳，不做删减）
        const distance =
          this.showData.length - this.showLimit * (this.CACHE_DEFAULT + 1)
        this.showData.splice(this.showData.length - distance, distance)
        this.tailIndex -= distance
        return distance
      }
    }
  }

  // 更新数据源
  updateDataSource(dataSource) {
    this.dataSource = dataSource
  }

  // 更新数据展示限制
  updateShowLimit(showLimit) {
    this.showLimit = showLimit
  }

  // 更新扩展参数
  updateExtras(key, data) {
    if (this.extras) {
      this.extras[key] = data
    }
  }
}
export { Dialog, ScrollModel }
